package com.nidu.demo.oauth2.model;

import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.exception.BizException;
import com.nidu.demo.base.BaseDeletableEntity;
import com.nidu.demo.base.BaseStatusEntity;
import com.nidu.demo.base.BaseTenantEntity;
import com.nidu.demo.common.constants.Constants;
import com.nidu.demo.common.enums.BooleanEnum;
import com.nidu.demo.common.enums.StatusEnum;
import com.nidu.demo.common.exception.ErrorCodeConstants;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.List;

/**
 * OAuth2客户端领域对象
 *
 * @author auto
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class OAuth2Client extends BaseTenantEntity implements BaseStatusEntity, BaseDeletableEntity {

    private Long id;

    /**
     * 客户端编码
     */
    private String clientCode;

    /**
     * 客户端密钥
     */
    private String clientSecret;

    /**
     * 授权范围
     */
    private List<String> scopes;

    /**
     * 重定向 URI
     */
    private String redirectUri;

    /**
     * 访问令牌的有效期
     */
    private Long accessTokenValiditySeconds;

    /**
     * 刷新令牌的有效期
     */
    private Long refreshTokenValiditySeconds;

    /**
     * 用户授权有效期
     */
    private Long approveValiditySeconds;

    /**
     * 状态
     */
    private Integer status;

    /**
     * 是否删除
     */
    private Boolean deleted;


    /**
     * 创建OAuth2客户端
     * @param clientCode
     * @param clientSecret
     * @param scopes
     * @param redirectUri
     * @param accessTokenValiditySeconds
     * @param refreshTokenValiditySeconds
     * @return
     */
    public static OAuth2Client create(String clientCode, String clientSecret, String scopes, String redirectUri, Long accessTokenValiditySeconds, Long refreshTokenValiditySeconds, Long approveValiditySeconds) {
        OAuth2Client oauth2Client = new OAuth2Client();
        oauth2Client.setClientCode(clientCode)
                .setClientSecret(clientSecret)
                .setScopes(StrUtil.isEmpty(scopes) ? null : StrUtil.split(scopes, ','))
                .setRedirectUri(redirectUri)
                .setAccessTokenValiditySeconds(accessTokenValiditySeconds)
                .setRefreshTokenValiditySeconds(refreshTokenValiditySeconds)
                .setApproveValiditySeconds(approveValiditySeconds);
        return oauth2Client;
    }

    /**
     * 更新OAuth2客户端
     * @param id
     * @param clientCode
     * @param clientSecret
]     * @param scopes
     * @param redirectUri
     * @return
     */
    public static OAuth2Client update(Long id, String clientCode, String clientSecret, String scopes, String redirectUri, Long accessTokenValiditySeconds, Long refreshTokenValiditySeconds, Long approveValiditySeconds) {
        OAuth2Client oauth2Client = new OAuth2Client();
        oauth2Client.setId(id)
                .setClientCode(clientCode)
                .setClientSecret(clientSecret)
                .setScopes(StrUtil.isEmpty(scopes) ? null : StrUtil.split(scopes, ','))
                .setRedirectUri(redirectUri)
                .setAccessTokenValiditySeconds(accessTokenValiditySeconds)
                .setRefreshTokenValiditySeconds(refreshTokenValiditySeconds)
                .setApproveValiditySeconds(approveValiditySeconds);
        return oauth2Client;
    }

    @Override
    public void isDeleted() {
        if (BooleanEnum.TRUE.getValue().equals(this.getDeleted())) {
            throw new BizException(ErrorCodeConstants.OAUTH2_CLIENT_NOT_FOUND.getCode(), ErrorCodeConstants.OAUTH2_CLIENT_NOT_FOUND.getMessage());
        }
    }

    @Override
    public void isDisable() {
        if (StatusEnum.DISABLE.getValue().equals(this.status)) {
            throw new BizException(ErrorCodeConstants.OAUTH2_CLIENT_STATUS_DISABLE.getCode(), ErrorCodeConstants.OAUTH2_CLIENT_STATUS_DISABLE.getMessage());
        }
    }

    public void validateRedirectUri(String redirectUri){
        if (!StrUtil.isEmpty(redirectUri) && !redirectUri.equals(this.getRedirectUri())) {
            throw new BizException(ErrorCodeConstants.OAUTH2_CLIENT_REDIRECT_URL_FAIL.getCode(), ErrorCodeConstants.OAUTH2_CLIENT_REDIRECT_URL_FAIL.getMessage());
        }
    }

    public void validateClientSecret(String clientSecret) {
        if (!StrUtil.isEmpty(clientSecret) && !clientSecret.equals(this.getClientSecret())) {
            throw new BizException(ErrorCodeConstants.OAUTH2_CLIENT_SECRET_FAIL.getCode(), ErrorCodeConstants.OAUTH2_CLIENT_SECRET_FAIL.getMessage());
        }
    }

    /**
     * 校验授权范围是否在允许范围内
     *
     * @param requestScopes 请求的授权范围
     * @throws BizException 如果请求的授权范围不在允许范围内
     */
    public void validateScopes(List<String> requestScopes) {
        if (requestScopes == null || requestScopes.isEmpty()) {
            return;
        }
        
        // 如果客户端没有配置授权范围，则允许所有范围
        if (Constants.DEFAULT_AUTH_SCOPES.equals(this.scopes)) {
            return;
        }

        // 检查请求的每个scope是否都在允许范围内
        for (String scope : requestScopes) {
            if (!this.scopes.contains(scope)) {
                throw new BizException(ErrorCodeConstants.OAUTH2_CLIENT_SCOPE_NO_FOUND.getCode(), ErrorCodeConstants.OAUTH2_CLIENT_SCOPE_NO_FOUND.getMessage());
            }
        }
    }

}